/*
 * SPDX-License-Identifier: GPL-2.0
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 * Description:
 * Author: -
 * Create:
 */

#include "ossl_knl.h"
#include "hiudk3.h"
#include "hiudk_internal.h"

/**
 * @brief hiudk_alloc_ceqs - alloc ceqs
 * @param udkdev: device pointer to udkdev
 * @param type: service type
 * @param num: alloc ceq number
 * @param ceq_id_array: alloc ceq_id_array
 * @param act_num: alloc actual number
 * @retval zero: success
 * @retval non-zero: failure
 */
int hiudk_alloc_ceqs(void *udkdev, enum hinic3_service_type type, int num, int *ceq_id_array, int *act_num)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return -EINVAL;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_alloc_ceqs != NULL))) {
        return ops->crm_ops.hiudk_alloc_ceqs(sdk_hwdev, type, num, ceq_id_array, act_num);
    }
    pr_err("ops is NULL! \n");
    return -EINVAL;
}

EXPORT_SYMBOL(hiudk_alloc_ceqs);

/**
 * @brief hiudk_alloc_irqs - alloc irq
 * @param udkdev: device pointer to udkdev
 * @param type: service type
 * @param num: alloc number
 * @param irq_info_array: alloc irq info
 * @param act_num: alloc actual number
 * @retval zero: success
 * @retval non-zero: failure
 */
int hiudk_alloc_irqs(void *udkdev, enum hinic3_service_type type, u16 num,
                     struct irq_info *irq_info_array, u16 *act_num)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return -EINVAL;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_alloc_irqs != NULL))) {
        return ops->crm_ops.hiudk_alloc_irqs(sdk_hwdev, type, num, irq_info_array, act_num);
    }
    pr_err("ops is NULL! \n");
    return -EINVAL;
}

EXPORT_SYMBOL(hiudk_alloc_irqs);

/*
 * @brief hiudk_ceq_num get toe ceq num
 */
u8 hiudk_ceq_num(void *udkdev)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return 0;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_ceq_num != NULL))) {
        return ops->crm_ops.hiudk_ceq_num(sdk_hwdev);
    }
    pr_err("ops is NULL! \n");
    return 0;
}

EXPORT_SYMBOL(hiudk_ceq_num);

/**
 * @brief hiudk_free_irq - free ceq
 * @param udkdev: device pointer to udkdev
 * @param type: service type
 * @param irq_id: ceq id
 */
void hiudk_free_ceq(void *udkdev, enum hinic3_service_type type, int ceq_id)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_free_ceq != NULL))) {
        return ops->crm_ops.hiudk_free_ceq(sdk_hwdev, type, ceq_id);
    }
    pr_err("ops is NULL! \n");
    return;
}

EXPORT_SYMBOL(hiudk_free_ceq);

/**
 * @brief hiudk_free_irq - free irq
 * @param udkdev: device pointer to udkdev
 * @param type: service type
 * @param irq_id: irq id
 */
void hiudk_free_irq(void *udkdev, enum hinic3_service_type type, u32 irq_id)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_free_irq != NULL))) {
        return ops->crm_ops.hiudk_free_irq(sdk_hwdev, type, irq_id);
    }
    pr_err("ops is NULL! \n");
    return;
}

EXPORT_SYMBOL(hiudk_free_irq);

/**
 * @brief hiudk_support_ppa - function support ppa
 * @param udkdev: device pointer to udkdev
 * @param cap: ppa service capbility
 * @retval zero: success
 * @retval non-zero: failure
 */
bool hiudk_support_ppa(void *udkdev, struct ppa_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_ppa != NULL))) {
        return ops->crm_ops.hiudk_support_ppa(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_ppa);

/**
 * @brief hiudk_support_fc - function support fc
 * @param udkdev: device pointer to udkdev
 * @param cap: fc service capbility
 * @retval true: function support fc
 * @retval false: function not support fc
 */
bool hiudk_support_fc(void *udkdev, struct fc_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_fc != NULL))) {
        return ops->crm_ops.hiudk_support_fc(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_fc);

/**
 * @brief hiudk_support_ipsec - function support ipsec
 * @param udkdev: device pointer to udkdev
 * @param cap: ipsec service capbility
 * @retval true: function support ipsec
 * @retval false: function not support ipsec
 */
bool hiudk_support_ipsec(void *udkdev, struct ipsec_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_ipsec != NULL))) {
        return ops->crm_ops.hiudk_support_ipsec(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_ipsec);

/**
 * @brief hiudk_support_migr - function support migrate
 * @param udkdev: device pointer to udkdev
 * @param cap: migrate service capbility
 * @retval zero: success
 * @retval non-zero: failure
 */
bool hiudk_support_migr(void *udkdev, struct migr_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_migr != NULL))) {
        return ops->crm_ops.hiudk_support_migr(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_migr);

/**
 * @brief hiudk_support_nic - function support nic
 * @param udkdev: device pointer to udkdev
 * @param cap: nic service capbility
 * @retval true: function support nic
 * @retval false: function not support nic
 */
bool hiudk_support_nic(void *udkdev, struct nic_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_nic != NULL))) {
        return ops->crm_ops.hiudk_support_nic(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_nic);

/**
 * @brief hiudk_support_ovs - function support ovs
 * @param udkdev: device pointer to udkdev
 * @param cap: ovs service capbility
 * @retval true: function support ovs
 * @retval false: function not support ovs
 */
bool hiudk_support_ovs(void *udkdev, struct ovs_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_ovs != NULL))) {
        return ops->crm_ops.hiudk_support_ovs(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_ovs);

/**
 * @brief hiudk_support_vbs - function support vbs
 * @param udkdev: device pointer to udkdev
 * @param cap: vbs service capbility
 * @retval true: function support vbs
 * @retval false: function not support vbs
 */
bool hiudk_support_vbs(void *udkdev, struct vbs_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_vbs != NULL))) {
        return ops->crm_ops.hiudk_support_vbs(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_vbs);

/**
 * @brief hiudk_support_rdma - function support rdma
 * @param udkdev: device pointer to udkdev
 * @param cap: rdma service capbility
 * @retval true: function support rdma
 * @retval false: function not support rdma
 */
bool hiudk_support_rdma(void *udkdev, struct rdma_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_rdma != NULL))) {
        return ops->crm_ops.hiudk_support_rdma(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_rdma);

/**
 * @brief hiudk_support_roce - function support roce
 * @param udkdev: device pointer to udkdev
 * @param cap: roce service capbility
 * @retval true: function support roce
 * @retval false: function not support roce
 */
bool hiudk_support_roce(void *udkdev, struct rdma_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_roce != NULL))) {
        return ops->crm_ops.hiudk_support_roce(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_roce);

/**
 * @brief hiudk_support_toe - sync time to hardware
 * @param udkdev: device pointer to udkdev
 * @param cap: toe service capbility
 * @retval zero: success
 * @retval non-zero: failure
 */
bool hiudk_support_toe(void *udkdev, struct toe_service_cap *cap)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_support_toe != NULL))) {
        return ops->crm_ops.hiudk_support_toe(sdk_hwdev, cap);
    }
    pr_err("ops is NULL! \n");
    return false;
}

EXPORT_SYMBOL(hiudk_support_toe);

/**
 * @brief hiudk_stateful_deinit - deinit stateful resource
 * @param udkdev: device pointer to udkdev
 */
void hiudk_stateful_deinit(void *udkdev)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_stateful_deinit != NULL))) {
        return ops->crm_ops.hiudk_stateful_deinit(sdk_hwdev);
    }
    pr_err("ops is NULL! \n");
    return;
}

EXPORT_SYMBOL(hiudk_stateful_deinit);

/**
 * @brief hiudk_stateful_init - init stateful resource
 * @param udkdev: device pointer to udkdev
 * @retval zero: success
 * @retval non-zero: failure
 */
int hiudk_stateful_init(void *udkdev)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return -EINVAL;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_stateful_init != NULL))) {
        return ops->crm_ops.hiudk_stateful_init(sdk_hwdev);
    }
    pr_err("ops is NULL! \n");
    return -EINVAL;
}

EXPORT_SYMBOL(hiudk_stateful_init);

/**
 * @brief hiudk_get_stateful_enable - get stateful status
 * @param udkdev: device pointer to udkdev
 * @retval stateful enabel status
 */
bool hiudk_get_stateful_enable(void *udkdev)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;

    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }

    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_get_stateful_enable != NULL))) {
        return ops->crm_ops.hiudk_get_stateful_enable(sdk_hwdev);
    }
    pr_err("ops is NULL! \n");
    return false;
}
EXPORT_SYMBOL(hiudk_get_stateful_enable);

/**
 * @brief hiudk_get_timer_enable - get stateful status
 * @param udkdev: device pointer to udkdev
 * @retval timer enabel status
 */
bool hiudk_get_timer_enable(void *udkdev)
{
    void *sdk_hwdev = NULL;
    struct hiudk_ops *ops = NULL;
 
    if (unlikely(udkdev == NULL)) {
        pr_err("udkdev is NULL! \n");
        return false;
    }
 
    sdk_hwdev = GET_SDKHWDEV_FROM_HIUDKHWDEV(udkdev);
    ops = GET_SDKOPS_FROM_HIUDKHWDEV(udkdev);
    if (likely((ops != NULL) && (ops->crm_ops.hiudk_get_timer_enable != NULL))) {
        return ops->crm_ops.hiudk_get_timer_enable(sdk_hwdev);
    }
    pr_err("ops is NULL! \n");
    return false;
}
EXPORT_SYMBOL(hiudk_get_timer_enable);